package com.czn.shopdemo.utils;

import io.swagger.annotations.ApiModelProperty;

import io.swagger.annotations.ApiModelProperty;
import org.apache.commons.codec.binary.Base64;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.ServletRequest;
import javax.servlet.http.HttpServletRequest;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.io.*;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Utils {

    private static Logger logger = LoggerFactory.getLogger(Utils.class);

    /**
     * 电话号码验证
     *
     * @param str
     * @return 验证通过返回true
     */
    public static boolean isPhone(final String str) {
        Pattern p = null;
        Matcher m = null;
        boolean b = false;
        p = Pattern.compile("^[1][3,4,5,7,8][0-9]{9}$"); // 验证手机号
        m = p.matcher(str);
        b = m.matches();
        return b;
    }

    public static boolean isEmail(final String str) {
        Pattern regex = Pattern.compile("[a-zA-Z0-9_.]+@[a-zA-Z0-9_]+(\\.[a-zA-Z0-9]+)+");
        Matcher m = regex.matcher(str);
        return m.matches();
    }

    public static String formatGroupFireTime(Date fireTime) {
        if (fireTime == null) {
            return "";
        }
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        return dateFormat.format(fireTime);
    }


    /**
     * 比较两个实体属性值，返回一个map以有差异的属性名为key，value为一个list分别存obj1,obj2此属性名的值
     *
     * @param obj1 进行属性比较的对象1
     * @param obj2 进行属性比较的对象2
     * @return 属性差异比较结果map
     */
    public static Map<String, Map> compareFields(Object obj1, Object obj2) throws Exception {
        try {
            //装返回值得
            Map<String, Map> map = new LinkedHashMap<>();
            // 只有两个对象都是同一类型的才有可比性
            if (obj1.getClass() == obj2.getClass()) {
                Class clazz = obj1.getClass();
                // 获取object的属性描述
                PropertyDescriptor[] pds = Introspector.getBeanInfo(clazz, Object.class).getPropertyDescriptors();
                // 这里就是所有的属性了
                for (PropertyDescriptor pd : pds) {
                    // 属性名
                    String name = pd.getName();
                    // get方法
                    Method readMethod = pd.getReadMethod();
                    // 在obj1上调用get方法等同于获得obj1的属性值
                    Object objBefore = readMethod.invoke(obj1);
                    // 在obj2上调用get方法等同于获得obj2的属性值
                    Object objAfter = readMethod.invoke(obj2);
                    if (objBefore instanceof Timestamp) {
                        objBefore = new Date(((Timestamp) objBefore).getTime());
                    }
                    if (objAfter instanceof Timestamp) {
                        objAfter = new Date(((Timestamp) objAfter).getTime());
                    }
                    if ((objBefore == null && objAfter == null) || readMethod.getReturnType().isAssignableFrom(List.class)) {
                        continue;
                    } else if (objBefore == null && objAfter != null) {
                        Map m = new LinkedHashMap();
                        m.put("objBefore", objBefore);
                        m.put("objAfter", objAfter);
                        map.put(name, m);
                        continue;
                    }
                    // 比较这两个值是否相等,不等则放入map
                    if (!objBefore.equals(objAfter)) {
                        Map m = new LinkedHashMap();
                        m.put("objBefore", objBefore);
                        m.put("objAfter", objAfter);
                        map.put(name, m);
                    }
                }

            } else {
                throw new Exception("对象类型不一致，不能完成对比");
            }
            return map;
        } catch (Exception e) {
            throw e;
        }
    }

    public static Map getApiModelProperty(String classPath) throws Exception {
        Map p = new HashMap();
        try {
            // 1.根据类路径获取类
            Class<?> c = Class.forName(classPath);
            // 2.获取类的属性
            Field[] declaredFields = c.getDeclaredFields();
            // 3.遍历属性，获取属性上ApiModelProperty的值，属性的名，存入Map
            if (declaredFields.length != 0) {
                for (Field field : declaredFields) {
                    if (field.getAnnotation(ApiModelProperty.class) != null && !field.getAnnotation(ApiModelProperty.class).hidden()) {
                        // key和value可根据需求存
                        // 这存的key为注解的值，value为类属性名
                        p.put(field.getName(), field.getAnnotation(ApiModelProperty.class).value());
                    }
                }
                return p;
            }
        } catch (ClassNotFoundException e) {
            throw e;
        }
        return null;
    }


    /**
     * 生成8位UUID
     *
     * @return 8位UUID
     */
    public static String getRandomNumCode(int number) {
        String codeNum = "";
        int[] numbers = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
        Random random = new Random();
        for (int i = 0; i < number; i++) {
            int next = random.nextInt(10000);//目的是产生足够随机的数，避免产生的数字重复率高的问题
            codeNum += numbers[next % 10];
        }
        //System.out.println(codeNum);
        return codeNum;
    }

    /**
     * 判断Map是否为空
     *
     * @param map 待判断的集合
     * @return集合为空,返回true , 反之 false
     */
    public static boolean isEmpityMap(Map map) {
        if (map == null) {
            return true;
        } else {
            if (map.isEmpty()) {
                return true;
            } else {
                return false;
            }
        }
    }

    /**
     * 判断一个字符串是否为空
     *
     * @param str
     * @return
     */
    public static boolean isEmptyStr(String str) {
        if (str == null) {
            return true;
        }
        str = str.trim();
        return str.isEmpty();
    }

    /**
     * 对集合去重 （无顺序）
     *
     * @param arlList 带去重的集合
     * @return 返回去重后的集合
     */
    public static List removeDuplicate(List arlList) {
        if (Utils.isEmpityCollection(arlList)) {
            return new ArrayList();
        }
        HashSet h = new HashSet(arlList);
        arlList.clear();
        arlList.addAll(h);
        return arlList;
    }

    /**
     * 判断对象是否为空
     *
     * @param obj
     * @return
     */
    public static boolean isNotNull(Object obj) {
        if (obj != null) {
            return true;
        }
        return false;
    }

    /**
     * 判断集合是否为空
     *
     * @param c 待判断的集合
     * @return集合为空,返回true , 反之 false
     */
    public static boolean isEmpityCollection(Collection c) {
        if (c == null || c.isEmpty()) {
            return true;
        } else {
            return false;
        }
    }

    public static boolean isEmptyStr(Object s) {
        return (s == null) || (s.toString().trim().length() == 0);
    }

    /**
     * 判断传入参数是否为空,空字符串""或"null"或"<null> 为了兼容ios的空获取到<null>字符串
     *
     * @param s 待判断参数
     * @return true 空 <br>
     * false 非空
     */
    public static boolean isEmptyString(Object s) {
        return (s == null) || (s.toString().trim().length() == 0) || s.toString().trim().equalsIgnoreCase("null") || s.toString().trim().equalsIgnoreCase("<null>");
    }

    /**
     * 对传入参数进行判断是否为空,为空则返回"",反之返回传入参数
     *
     * @param v 传入参数
     * @return 处理后的参数
     */
    public static String filterNullValue(String v) {
        return isEmptyString(v) ? "" : v;
    }


    /**
     * 将base64编码的字符串转换成图片保存到相应的路径
     *
     * @param imageInf 图片 字符串
     * @param path     保存的路径
     * @return 是否保存成功状态
     * @throws java.io.IOException IO读写错误
     */
    public static boolean saveFileToDisk(String imageInf, String path) {//对字节数组字符串进行Base64解码并生成图片
        OutputStream out = null;
        try {
            if (imageInf == null) {
                //图像数据为空
                return false;
            }
            //Base64解码
            byte[] b = Base64.decodeBase64(imageInf);
            for (int i = 0; i < b.length; ++i) {
                if (b[i] < 0) {//调整异常数据
                    b[i] += 256;
                }
            }
            //生成jpeg图片
            out = new FileOutputStream(path);
            out.write(b);
            out.flush();
            return true;
        } catch (IOException e) {
            logger.error(e.getMessage());
            return false;
        } finally {
            if (out != null) {
                try {
                    out.close();
                } catch (IOException e) {
                    logger.error(e.getMessage());
                }
            }
        }
    }

    /**
     * 从servletRequest inputStream 获取原始字符串
     *
     * @param request
     * @return
     */
    public static String getStrFromReqInputStrem(ServletRequest request) {
        try {
            if (request == null) return "";
            InputStream in = request.getInputStream();
            int len = request.getContentLength();
            if (len <= 0) return "";
            byte[] buffer = new byte[len];
            while (in.read(buffer) > 0) {
                String s = new String(buffer, "UTF-8");
                return s;
            }
            return "";
        } catch (Exception e) {
            logger.error(e.getMessage());
            return "";
        }

    }

    /**
     * 验证手机号码、邮箱，邮编的合法性
     *
     * @param objValue 手机号码、邮箱，邮编
     * @return 返回手机号码、邮箱，邮编的合法性 true 合法， false 不合法
     */
    public static Boolean CheckParamValidity(String objValue, String tip) {
        if (isEmptyString(objValue)) {
            return false;
        }
        String regExp = "^((13[0-9])|(15[^4,\\D])|(17[^4,\\D])|(18[0,5-9]))\\d{8}$";//默认手机
        if ("1".equals(tip)) {//邮箱
            regExp = "^([a-zA-Z0-9_\\-\\.]+)@((\\[[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.)|(([a-zA-Z0-9\\-]+\\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\\]?)$";
        } else if ("2".equals(tip)) {//邮编
            regExp = "[1-9]\\d{5}(?!\\d)";
        }
        Pattern p = Pattern.compile(regExp);
        Matcher m = p.matcher(filterNullValue(objValue));
        return m.matches();
    }

    /**
     * 获取远程IP地址
     *
     * @param @return
     * @return String
     * @throws
     * @Title: getRemoteIp
     * @author Jason
     */
    public static String getRemoteIp() {
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        if (request.getHeader("x-forwarded-for") == null) {
            return request.getRemoteAddr();
        }
        return request.getHeader("x-forwarded-for");
    }


    public static void uploadFile(MultipartFile multipartFile, String filePath) throws Exception {
        FileOutputStream fos = null;
        FileInputStream fs = null;
        Long fileSize = 0L;
        try {
            fs = (FileInputStream) multipartFile.getInputStream();
            filePath = filePath.startsWith("/") ? filePath : System.getProperty("user.dir") + "/" + filePath;
            if (!FileUtil.isDir(filePath)) {
                FileUtil.createDir(filePath);
            }
            File file = new File(filePath + "/" + multipartFile.getOriginalFilename());
            fos = new FileOutputStream(file);
            byte[] buffer = new byte[1024];
            int len = 0;
            while ((len = fs.read(buffer)) != -1) {
                fos.write(buffer, 0, len);
            }
        } catch (Exception e) {
            logger.error(e.getMessage());
            throw new Exception(e.getMessage());
        } finally {
            if (fos != null) {
                fos.close();
            }
            if (fs != null) {
                fs.close();
            }
        }
    }

    public static void checkParameter(Object... parameters) throws Exception {
        for (Object parameter : parameters) {
            if (isEmptyStr(parameter)) {
                throw new Exception("必填参数为空");
            }
        }
    }

}